#include "internal.h"

static void reweight_entity(struct cfs_rq *cfs_rq, struct sched_entity *se,
                            unsigned long weight)
{
    bool curr = cfs_rq->curr == se;

    if (se->on_rq)
    {
        /* commit outstanding execution time */
        update_curr(cfs_rq);
        update_entity_lag(cfs_rq, se);
        se->deadline -= se->vruntime;
        se->rel_deadline = 1;
        if (!curr)
            __dequeue_entity(cfs_rq, se);
        update_load_sub(&cfs_rq->load, se->load.weight);
    }
    dequeue_load_avg(cfs_rq, se);

    /*
     * Because we keep se->vlag = V - v_i, while: lag_i = w_i*(V - v_i),
     * we need to scale se->vlag when w_i changes.
     */
    se->vlag = div_s64(se->vlag * se->load.weight, weight);
    if (se->rel_deadline)
        se->deadline = div_s64(se->deadline * se->load.weight, weight);

    update_load_set(&se->load, weight);

#ifdef CONFIG_SMP
    do
    {
        u32 divider = get_pelt_divider(&se->avg);

        se->avg.load_avg = div_u64(se_weight(se) * se->avg.load_sum, divider);
    } while (0);
#endif

    enqueue_load_avg(cfs_rq, se);
    if (se->on_rq)
    {
        update_load_add(&cfs_rq->load, se->load.weight);
        place_entity(cfs_rq, se, 0);
        if (!curr)
            __enqueue_entity(cfs_rq, se);

        /*
         * The entity's vruntime has been adjusted, so let's check
         * whether the rq-wide min_vruntime needs updated too. Since
         * the calculations above require stable min_vruntime rather
         * than up-to-date one, we do the update at the end of the
         * reweight process.
         */
        update_min_vruntime(cfs_rq);
    }
}

static void reweight_task_fair(struct rq *rq, struct task_struct *p,
                               const struct load_weight *lw)
{
    struct sched_entity *se = &p->se;
    struct cfs_rq *cfs_rq = cfs_rq_of(se);
    struct load_weight *load = &se->load;

    reweight_entity(cfs_rq, se, lw->weight);
    load->inv_weight = lw->inv_weight;
}
